{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "\n",
    "import math\n",
    "\n",
    "from IPython import display\n",
    "from matplotlib import cm\n",
    "from matplotlib import gridspec\n",
    "from matplotlib import pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from sklearn import metrics\n",
    "import tensorflow as tf\n",
    "from tensorflow.python.data import Dataset\n",
    "\n",
    "tf.logging.set_verbosity(tf.logging.ERROR)\n",
    "pd.options.display.max_rows = 10\n",
    "pd.options.display.float_format = '{:.1f}'.format\n",
    "\n",
    "california_housing_dataframe = pd.read_csv(\"https://dl.google.com/mlcc/mledu-datasets/california_housing_train.csv\", sep=\",\")\n",
    "\n",
    "california_housing_dataframe = california_housing_dataframe.reindex(\n",
    "    np.random.permutation(california_housing_dataframe.index))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def preprocess_features(california_housing_dataframe):\n",
    "  \"\"\"Prepares input features from California housing data set.\n",
    "\n",
    "  Args:\n",
    "    california_housing_dataframe: A Pandas DataFrame expected to contain data\n",
    "      from the California housing data set.\n",
    "  Returns:\n",
    "    A DataFrame that contains the features to be used for the model, including\n",
    "    synthetic features.\n",
    "  \"\"\"\n",
    "  selected_features = california_housing_dataframe[\n",
    "    [\"latitude\",\n",
    "     \"longitude\",\n",
    "     \"housing_median_age\",\n",
    "     \"total_rooms\",\n",
    "     \"total_bedrooms\",\n",
    "     \"population\",\n",
    "     \"households\",\n",
    "     \"median_income\"]]\n",
    "  processed_features = selected_features.copy()\n",
    "  # Create a synthetic feature.\n",
    "  processed_features[\"rooms_per_person\"] = (\n",
    "    california_housing_dataframe[\"total_rooms\"] /\n",
    "    california_housing_dataframe[\"population\"])\n",
    "  return processed_features\n",
    "\n",
    "def preprocess_targets(california_housing_dataframe):\n",
    "  \"\"\"Prepares target features (i.e., labels) from California housing data set.\n",
    "\n",
    "  Args:\n",
    "    california_housing_dataframe: A Pandas DataFrame expected to contain data\n",
    "      from the California housing data set.\n",
    "  Returns:\n",
    "    A DataFrame that contains the target feature.\n",
    "  \"\"\"\n",
    "  output_targets = pd.DataFrame()\n",
    "  # Create a boolean categorical feature representing whether the\n",
    "  # medianHouseValue is above a set threshold.\n",
    "  output_targets[\"median_house_value_is_high\"] = (\n",
    "    california_housing_dataframe[\"median_house_value\"] > 265000).astype(float)\n",
    "  return output_targets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training examples summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>latitude</th>\n",
       "      <th>longitude</th>\n",
       "      <th>housing_median_age</th>\n",
       "      <th>total_rooms</th>\n",
       "      <th>total_bedrooms</th>\n",
       "      <th>population</th>\n",
       "      <th>households</th>\n",
       "      <th>median_income</th>\n",
       "      <th>rooms_per_person</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>35.6</td>\n",
       "      <td>-119.6</td>\n",
       "      <td>28.6</td>\n",
       "      <td>2629.4</td>\n",
       "      <td>537.2</td>\n",
       "      <td>1423.5</td>\n",
       "      <td>500.0</td>\n",
       "      <td>3.9</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>2.1</td>\n",
       "      <td>2.0</td>\n",
       "      <td>12.6</td>\n",
       "      <td>2123.4</td>\n",
       "      <td>414.0</td>\n",
       "      <td>1140.5</td>\n",
       "      <td>378.5</td>\n",
       "      <td>1.9</td>\n",
       "      <td>1.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>32.5</td>\n",
       "      <td>-124.3</td>\n",
       "      <td>1.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>6.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>33.9</td>\n",
       "      <td>-121.8</td>\n",
       "      <td>18.0</td>\n",
       "      <td>1463.0</td>\n",
       "      <td>298.0</td>\n",
       "      <td>792.0</td>\n",
       "      <td>282.0</td>\n",
       "      <td>2.6</td>\n",
       "      <td>1.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>34.2</td>\n",
       "      <td>-118.5</td>\n",
       "      <td>29.0</td>\n",
       "      <td>2132.5</td>\n",
       "      <td>433.0</td>\n",
       "      <td>1169.5</td>\n",
       "      <td>409.5</td>\n",
       "      <td>3.5</td>\n",
       "      <td>1.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>37.7</td>\n",
       "      <td>-118.0</td>\n",
       "      <td>37.0</td>\n",
       "      <td>3137.0</td>\n",
       "      <td>648.0</td>\n",
       "      <td>1706.2</td>\n",
       "      <td>604.0</td>\n",
       "      <td>4.7</td>\n",
       "      <td>2.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>42.0</td>\n",
       "      <td>-114.5</td>\n",
       "      <td>52.0</td>\n",
       "      <td>32627.0</td>\n",
       "      <td>6445.0</td>\n",
       "      <td>35682.0</td>\n",
       "      <td>6082.0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>55.2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       latitude  longitude  housing_median_age  total_rooms  total_bedrooms  \\\n",
       "count   12000.0    12000.0             12000.0      12000.0         12000.0   \n",
       "mean       35.6     -119.6                28.6       2629.4           537.2   \n",
       "std         2.1        2.0                12.6       2123.4           414.0   \n",
       "min        32.5     -124.3                 1.0          2.0             1.0   \n",
       "25%        33.9     -121.8                18.0       1463.0           298.0   \n",
       "50%        34.2     -118.5                29.0       2132.5           433.0   \n",
       "75%        37.7     -118.0                37.0       3137.0           648.0   \n",
       "max        42.0     -114.5                52.0      32627.0          6445.0   \n",
       "\n",
       "       population  households  median_income  rooms_per_person  \n",
       "count     12000.0     12000.0        12000.0           12000.0  \n",
       "mean       1423.5       500.0            3.9               2.0  \n",
       "std        1140.5       378.5            1.9               1.2  \n",
       "min           6.0         1.0            0.5               0.1  \n",
       "25%         792.0       282.0            2.6               1.5  \n",
       "50%        1169.5       409.5            3.5               1.9  \n",
       "75%        1706.2       604.0            4.7               2.3  \n",
       "max       35682.0      6082.0           15.0              55.2  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Validation examples summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>latitude</th>\n",
       "      <th>longitude</th>\n",
       "      <th>housing_median_age</th>\n",
       "      <th>total_rooms</th>\n",
       "      <th>total_bedrooms</th>\n",
       "      <th>population</th>\n",
       "      <th>households</th>\n",
       "      <th>median_income</th>\n",
       "      <th>rooms_per_person</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>35.6</td>\n",
       "      <td>-119.5</td>\n",
       "      <td>28.5</td>\n",
       "      <td>2677.9</td>\n",
       "      <td>544.7</td>\n",
       "      <td>1444.2</td>\n",
       "      <td>504.2</td>\n",
       "      <td>3.9</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>2.1</td>\n",
       "      <td>2.0</td>\n",
       "      <td>12.6</td>\n",
       "      <td>2309.9</td>\n",
       "      <td>438.9</td>\n",
       "      <td>1165.3</td>\n",
       "      <td>398.7</td>\n",
       "      <td>1.9</td>\n",
       "      <td>0.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>32.5</td>\n",
       "      <td>-124.3</td>\n",
       "      <td>2.0</td>\n",
       "      <td>11.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>33.9</td>\n",
       "      <td>-121.8</td>\n",
       "      <td>18.0</td>\n",
       "      <td>1457.8</td>\n",
       "      <td>295.0</td>\n",
       "      <td>783.0</td>\n",
       "      <td>279.0</td>\n",
       "      <td>2.6</td>\n",
       "      <td>1.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>34.2</td>\n",
       "      <td>-118.5</td>\n",
       "      <td>29.0</td>\n",
       "      <td>2117.0</td>\n",
       "      <td>435.0</td>\n",
       "      <td>1160.5</td>\n",
       "      <td>408.0</td>\n",
       "      <td>3.6</td>\n",
       "      <td>1.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>37.7</td>\n",
       "      <td>-118.0</td>\n",
       "      <td>37.0</td>\n",
       "      <td>3173.5</td>\n",
       "      <td>650.2</td>\n",
       "      <td>1755.0</td>\n",
       "      <td>607.0</td>\n",
       "      <td>4.8</td>\n",
       "      <td>2.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>41.9</td>\n",
       "      <td>-114.3</td>\n",
       "      <td>52.0</td>\n",
       "      <td>37937.0</td>\n",
       "      <td>5471.0</td>\n",
       "      <td>16122.0</td>\n",
       "      <td>5189.0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>19.1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       latitude  longitude  housing_median_age  total_rooms  total_bedrooms  \\\n",
       "count    5000.0     5000.0              5000.0       5000.0          5000.0   \n",
       "mean       35.6     -119.5                28.5       2677.9           544.7   \n",
       "std         2.1        2.0                12.6       2309.9           438.9   \n",
       "min        32.5     -124.3                 2.0         11.0             3.0   \n",
       "25%        33.9     -121.8                18.0       1457.8           295.0   \n",
       "50%        34.2     -118.5                29.0       2117.0           435.0   \n",
       "75%        37.7     -118.0                37.0       3173.5           650.2   \n",
       "max        41.9     -114.3                52.0      37937.0          5471.0   \n",
       "\n",
       "       population  households  median_income  rooms_per_person  \n",
       "count      5000.0      5000.0         5000.0            5000.0  \n",
       "mean       1444.2       504.2            3.9               2.0  \n",
       "std        1165.3       398.7            1.9               0.9  \n",
       "min           3.0         4.0            0.5               0.0  \n",
       "25%         783.0       279.0            2.6               1.5  \n",
       "50%        1160.5       408.0            3.6               1.9  \n",
       "75%        1755.0       607.0            4.8               2.3  \n",
       "max       16122.0      5189.0           15.0              19.1  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training targets summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>median_house_value_is_high</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>12000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       median_house_value_is_high\n",
       "count                     12000.0\n",
       "mean                          0.2\n",
       "std                           0.4\n",
       "min                           0.0\n",
       "25%                           0.0\n",
       "50%                           0.0\n",
       "75%                           0.0\n",
       "max                           1.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Validation targets summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>median_house_value_is_high</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>5000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       median_house_value_is_high\n",
       "count                      5000.0\n",
       "mean                          0.3\n",
       "std                           0.4\n",
       "min                           0.0\n",
       "25%                           0.0\n",
       "50%                           0.0\n",
       "75%                           1.0\n",
       "max                           1.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Choose the first 12000 (out of 17000) examples for training.\n",
    "training_examples = preprocess_features(california_housing_dataframe.head(12000))\n",
    "training_targets = preprocess_targets(california_housing_dataframe.head(12000))\n",
    "\n",
    "# Choose the last 5000 (out of 17000) examples for validation.\n",
    "validation_examples = preprocess_features(california_housing_dataframe.tail(5000))\n",
    "validation_targets = preprocess_targets(california_housing_dataframe.tail(5000))\n",
    "\n",
    "# Double-check that we've done the right thing.\n",
    "print(\"Training examples summary:\")\n",
    "display.display(training_examples.describe())\n",
    "print(\"Validation examples summary:\")\n",
    "display.display(validation_examples.describe())\n",
    "\n",
    "print(\"Training targets summary:\")\n",
    "display.display(training_targets.describe())\n",
    "print(\"Validation targets summary:\")\n",
    "display.display(validation_targets.describe())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def construct_feature_columns(input_features):\n",
    "  \"\"\"Construct the TensorFlow Feature Columns.\n",
    "\n",
    "  Args:\n",
    "    input_features: The names of the numerical input features to use.\n",
    "  Returns:\n",
    "    A set of feature columns\n",
    "  \"\"\"\n",
    "  return set([tf.feature_column.numeric_column(my_feature)\n",
    "              for my_feature in input_features])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):\n",
    "    \"\"\"Trains a linear regression model of one feature.\n",
    "  \n",
    "    Args:\n",
    "      features: pandas DataFrame of features\n",
    "      targets: pandas DataFrame of targets\n",
    "      batch_size: Size of batches to be passed to the model\n",
    "      shuffle: True or False. Whether to shuffle the data.\n",
    "      num_epochs: Number of epochs for which data should be repeated. None = repeat indefinitely\n",
    "    Returns:\n",
    "      Tuple of (features, labels) for next data batch\n",
    "    \"\"\"\n",
    "    \n",
    "    # Convert pandas data into a dict of np arrays.\n",
    "    features = {key:np.array(value) for key,value in dict(features).items()}                                            \n",
    " \n",
    "    # Construct a dataset, and configure batching/repeating\n",
    "    ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit\n",
    "    ds = ds.batch(batch_size).repeat(num_epochs)\n",
    "    \n",
    "    # Shuffle the data, if specified\n",
    "    if shuffle:\n",
    "      ds = ds.shuffle(10000)\n",
    "    \n",
    "    # Return the next batch of data\n",
    "    features, labels = ds.make_one_shot_iterator().get_next()\n",
    "    return features, labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_linear_regressor_model(\n",
    "    learning_rate,\n",
    "    steps,\n",
    "    batch_size,\n",
    "    training_examples,\n",
    "    training_targets,\n",
    "    validation_examples,\n",
    "    validation_targets):\n",
    "  \"\"\"Trains a linear regression model.\n",
    "  \n",
    "  In addition to training, this function also prints training progress information,\n",
    "  as well as a plot of the training and validation loss over time.\n",
    "  \n",
    "  Args:\n",
    "    learning_rate: A `float`, the learning rate.\n",
    "    steps: A non-zero `int`, the total number of training steps. A training step\n",
    "      consists of a forward and backward pass using a single batch.\n",
    "    batch_size: A non-zero `int`, the batch size.\n",
    "    training_examples: A `DataFrame` containing one or more columns from\n",
    "      `california_housing_dataframe` to use as input features for training.\n",
    "    training_targets: A `DataFrame` containing exactly one column from\n",
    "      `california_housing_dataframe` to use as target for training.\n",
    "    validation_examples: A `DataFrame` containing one or more columns from\n",
    "      `california_housing_dataframe` to use as input features for validation.\n",
    "    validation_targets: A `DataFrame` containing exactly one column from\n",
    "      `california_housing_dataframe` to use as target for validation.\n",
    "      \n",
    "  Returns:\n",
    "    A `LinearRegressor` object trained on the training data.\n",
    "  \"\"\"\n",
    "\n",
    "  periods = 10\n",
    "  steps_per_period = steps / periods\n",
    "\n",
    "  # Create a linear regressor object.\n",
    "  my_optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)\n",
    "  my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)\n",
    "  linear_regressor = tf.estimator.LinearRegressor(\n",
    "      feature_columns=construct_feature_columns(training_examples),\n",
    "      optimizer=my_optimizer\n",
    "  )\n",
    "    \n",
    "  # Create input functions  \n",
    "  training_input_fn = lambda: my_input_fn(training_examples, \n",
    "                                          training_targets[\"median_house_value_is_high\"], \n",
    "                                          batch_size=batch_size)\n",
    "  predict_training_input_fn = lambda: my_input_fn(training_examples, \n",
    "                                                  training_targets[\"median_house_value_is_high\"], \n",
    "                                                  num_epochs=1, \n",
    "                                                  shuffle=False)\n",
    "  predict_validation_input_fn = lambda: my_input_fn(validation_examples, \n",
    "                                                    validation_targets[\"median_house_value_is_high\"], \n",
    "                                                    num_epochs=1, \n",
    "                                                    shuffle=False)\n",
    "\n",
    "  # Train the model, but do so inside a loop so that we can periodically assess\n",
    "  # loss metrics.\n",
    "  print(\"Training model...\")\n",
    "  print(\"RMSE (on training data):\")\n",
    "  training_rmse = []\n",
    "  validation_rmse = []\n",
    "  for period in range (0, periods):\n",
    "    # Train the model, starting from the prior state.\n",
    "    linear_regressor.train(\n",
    "        input_fn=training_input_fn,\n",
    "        steps=steps_per_period\n",
    "    )\n",
    "    \n",
    "    # Take a break and compute predictions.\n",
    "    training_predictions = linear_regressor.predict(input_fn=predict_training_input_fn)\n",
    "    training_predictions = np.array([item['predictions'][0] for item in training_predictions])\n",
    "    \n",
    "    validation_predictions = linear_regressor.predict(input_fn=predict_validation_input_fn)\n",
    "    validation_predictions = np.array([item['predictions'][0] for item in validation_predictions])\n",
    "    \n",
    "    # Compute training and validation loss.\n",
    "    training_root_mean_squared_error = math.sqrt(\n",
    "        metrics.mean_squared_error(training_predictions, training_targets))\n",
    "    validation_root_mean_squared_error = math.sqrt(\n",
    "        metrics.mean_squared_error(validation_predictions, validation_targets))\n",
    "    # Occasionally print the current loss.\n",
    "    print(\"  period %02d : %0.2f\" % (period, training_root_mean_squared_error))\n",
    "    # Add the loss metrics from this period to our list.\n",
    "    training_rmse.append(training_root_mean_squared_error)\n",
    "    validation_rmse.append(validation_root_mean_squared_error)\n",
    "  print(\"Model training finished.\")\n",
    "  \n",
    "  # Output a graph of loss metrics over periods.\n",
    "  plt.ylabel(\"RMSE\")\n",
    "  plt.xlabel(\"Periods\")\n",
    "  plt.title(\"Root Mean Squared Error vs. Periods\")\n",
    "  plt.tight_layout()\n",
    "  plt.plot(training_rmse, label=\"training\")\n",
    "  plt.plot(validation_rmse, label=\"validation\")\n",
    "  plt.legend()\n",
    "\n",
    "  return linear_regressor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training model...\n",
      "RMSE (on training data):\n",
      "  period 00 : 0.45\n",
      "  period 01 : 0.45\n",
      "  period 02 : 0.45\n",
      "  period 03 : 0.44\n",
      "  period 04 : 0.44\n",
      "  period 05 : 0.44\n",
      "  period 06 : 0.44\n",
      "  period 07 : 0.44\n",
      "  period 08 : 0.44\n",
      "  period 09 : 0.44\n",
      "Model training finished.\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "linear_regressor = train_linear_regressor_model(\n",
    "    learning_rate=0.000001,\n",
    "    steps=200,\n",
    "    batch_size=20,\n",
    "    training_examples=training_examples,\n",
    "    training_targets=training_targets,\n",
    "    validation_examples=validation_examples,\n",
    "    validation_targets=validation_targets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Assignment 1:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAD8CAYAAAB+UHOxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAADX1JREFUeJzt3X+o3Xd9x/Hny6T+AJmt9upKEpaCYVgHVgk1w39G69pYx9INC5GhQQL5pwMFYavbH8UfhfqPHcIUyhqMItaijhYtlKy2FGG2TbV2tllpps5eWkwkbVXEjtT3/rif6LW9yTk3vb3n3ryfD7jc8/18P+ecz/fQ5nnPOd97bqoKSVI/r5j1AiRJs2EAJKkpAyBJTRkASWrKAEhSUwZAkpoyAJLUlAGQpKYMgCQ1tXHWCzid888/v7Zu3TrrZUjSuvLggw/+vKrmJs1b0wHYunUrhw4dmvUyJGldSfK/08zzJSBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU0ZAElqak3/JrCWZ+u135rZff/khvfO7L4lnRmfAUhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqSkDIElNGQBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU1NHYAkG5J8P8k3x/aFSe5L8niSryZ55Rh/1dg+MvZvXXQbHxvjjyW5YqUPRpI0veU8A/gwcHjR9qeBG6tqG/A0sHeM7wWerqo3AzeOeSS5CNgNvBXYCXwuyYaXtnxJ0pmaKgBJNgPvBf5tbAe4FPjamHIAuGpc3jW2GfsvG/N3AbdU1XNV9WPgCHDJShyEJGn5pn0G8C/APwC/HdtvAJ6pqhNjex7YNC5vAp4AGPufHfN/N77EdX4nyb4kh5IcOnbs2DIORZK0HBMDkOSvgKNV9eDi4SWm1oR9p7vO7weqbqqq7VW1fW5ubtLyJElnaJo/Cv8u4K+TXAm8GvgjFp4RnJtk4/gpfzPw5Jg/D2wB5pNsBF4HHF80ftLi60iSVtnEZwBV9bGq2lxVW1l4E/fbVfV3wN3A+8a0PcBt4/LtY5ux/9tVVWN89zhL6EJgG3D/ih2JJGlZpnkGcCr/CNyS5FPA94Gbx/jNwJeSHGHhJ//dAFX1SJJbgUeBE8A1VfX8S7h/SdJLsKwAVNU9wD3j8o9Y4iyeqvoNcPUprn89cP1yFylJWnn+JrAkNWUAJKkpAyBJTRkASWrKAEhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqSkDIElNGQBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU0ZAElqygBIUlMGQJKaMgCS1JQBkKSmDIAkNWUAJKkpAyBJTRkASWrKAEhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqSkDIElNGQBJasoASFJTBkCSmpoYgCSvTnJ/kh8keSTJx8f4hUnuS/J4kq8meeUYf9XYPjL2b110Wx8b448lueLlOihJ0mTTPAN4Dri0qt4GXAzsTLID+DRwY1VtA54G9o75e4Gnq+rNwI1jHkkuAnYDbwV2Ap9LsmElD0aSNL2JAagFvxqb54yvAi4FvjbGDwBXjcu7xjZj/2VJMsZvqarnqurHwBHgkhU5CknSsk31HkCSDUkeAo4CB4H/AZ6pqhNjyjywaVzeBDwBMPY/C7xh8fgS11l8X/uSHEpy6NixY8s/IknSVKYKQFU9X1UXA5tZ+Kn9LUtNG99zin2nGn/hfd1UVduravvc3Nw0y5MknYFlnQVUVc8A9wA7gHOTbBy7NgNPjsvzwBaAsf91wPHF40tcR5K0yqY5C2guybnj8muAdwOHgbuB941pe4DbxuXbxzZj/7erqsb47nGW0IXANuD+lToQSdLybJw8hQuAA+OMnVcAt1bVN5M8CtyS5FPA94Gbx/ybgS8lOcLCT/67AarqkSS3Ao8CJ4Brqur5lT0cSdK0Jgagqh4G3r7E+I9Y4iyeqvoNcPUpbut64PrlL1OStNL8TWBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU0ZAElqygBIUlMGQJKaMgCS1JQBkKSmDIAkNWUAJKkpAyBJTRkASWrKAEhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqSkDIElNGQBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU0ZAElqygBIUlMGQJKaMgCS1JQBkKSmJgYgyZYkdyc5nOSRJB8e469PcjDJ4+P7eWM8ST6b5EiSh5O8Y9Ft7RnzH0+y5+U7LEnSJNM8AzgBfLSq3gLsAK5JchFwLXBXVW0D7hrbAO8Bto2vfcDnYSEYwHXAO4FLgOtORkOStPomBqCqnqqq743LvwQOA5uAXcCBMe0AcNW4vAv4Yi34LnBukguAK4CDVXW8qp4GDgI7V/RoJElTW9Z7AEm2Am8H7gPeVFVPwUIkgDeOaZuAJxZdbX6MnWpckjQDUwcgyWuBrwMfqapfnG7qEmN1mvEX3s++JIeSHDp27Ni0y5MkLdNUAUhyDgv/+H+5qr4xhn82XtphfD86xueBLYuuvhl48jTjf6Cqbqqq7VW1fW5ubjnHIklahmnOAgpwM3C4qj6zaNftwMkzefYAty0a/+A4G2gH8Ox4iehO4PIk5403fy8fY5KkGdg4xZx3AR8A/ivJQ2Psn4AbgFuT7AV+Clw99t0BXAkcAX4NfAigqo4n+STwwJj3iao6viJHIUlatokBqKrvsPTr9wCXLTG/gGtOcVv7gf3LWaAk6eXhbwJLUlMGQJKaMgCS1JQBkKSmDIAkNWUAJKkpAyBJTRkASWrKAEhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqSkDIElNGQBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU0ZAElqygBIUlMGQJKaMgCS1JQBkKSmDIAkNWUAJKkpAyBJTRkASWrKAEhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqamJAUiyP8nRJD9cNPb6JAeTPD6+nzfGk+SzSY4keTjJOxZdZ8+Y/3iSPS/P4UiSpjXNM4AvADtfMHYtcFdVbQPuGtsA7wG2ja99wOdhIRjAdcA7gUuA605GQ5I0GxMDUFX3AsdfMLwLODAuHwCuWjT+xVrwXeDcJBcAVwAHq+p4VT0NHOTFUZEkraIzfQ/gTVX1FMD4/sYxvgl4YtG8+TF2qnFJ0oys9JvAWWKsTjP+4htI9iU5lOTQsWPHVnRxkqTfO9MA/Gy8tMP4fnSMzwNbFs3bDDx5mvEXqaqbqmp7VW2fm5s7w+VJkiY50wDcDpw8k2cPcNui8Q+Os4F2AM+Ol4juBC5Pct548/fyMSZJmpGNkyYk+QrwF8D5SeZZOJvnBuDWJHuBnwJXj+l3AFcCR4BfAx8CqKrjST4JPDDmfaKqXvjGsiRpFU0MQFW9/xS7LltibgHXnOJ29gP7l7U6SdLLxt8ElqSmDIAkNWUAJKkpAyBJTRkASWrKAEhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqSkDIElNGQBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU0ZAElqauOsF6Czw9ZrvzWT+/3JDe+dyf1KZwOfAUhSUwZAkpoyAJLUlAGQpKYMgCQ1ZQAkqSkDIElNGQBJasoASFJTBkCSmjIAktSUAZCkpgyAJDVlACSpKQMgSU0ZAElqatUDkGRnkseSHEly7WrfvyRpwar+RbAkG4B/Bf4SmAceSHJ7VT26muvQ2WNWf4kM/GtkWv9W+09CXgIcqaofASS5BdgFnFUBmOU/SpI0rdUOwCbgiUXb88A7V3kN0orw7yBrvVvtAGSJsfqDCck+YN/Y/FWSx05xW+cDP1/BtZ1tfHwmW5ePUT69qne3Lh+jVbRWH58/mWbSagdgHtiyaHsz8OTiCVV1E3DTpBtKcqiqtq/s8s4ePj6T+RhN5mN0euv98Vnts4AeALYluTDJK4HdwO2rvAZJEqv8DKCqTiT5e+BOYAOwv6oeWc01SJIWrPZLQFTVHcAdK3BTE18mas7HZzIfo8l8jE5vXT8+qarJsyRJZx0/CkKSmlrXAUhydZJHkvw2ybp9J36l+XEbp5dkf5KjSX4467WsRUm2JLk7yeHx/9eHZ72mtSbJq5Pcn+QH4zH6+KzXdCbWdQCAHwJ/C9w764WsFYs+buM9wEXA+5NcNNtVrTlfAHbOehFr2Ango1X1FmAHcI3/Db3Ic8ClVfU24GJgZ5IdM17Tsq3rAFTV4ao61S+KdfW7j9uoqv8DTn7choaquhc4Put1rFVV9VRVfW9c/iVwmIXf4tdQC341Ns8ZX+vuDdV1HQAtaamP2/B/Xp2RJFuBtwP3zXYla0+SDUkeAo4CB6tq3T1Gq34a6HIl+Q/gj5fY9c9Vddtqr2cdmPhxG9I0krwW+Drwkar6xazXs9ZU1fPAxUnOBf49yZ9V1bp6X2nNB6Cq3j3rNawzEz9uQ5okyTks/OP/5ar6xqzXs5ZV1TNJ7mHhfaV1FQBfAjr7+HEbekmSBLgZOFxVn5n1etaiJHPjJ3+SvAZ4N/Dfs13V8q3rACT5myTzwJ8D30py56zXNGtVdQI4+XEbh4Fb/biNP5TkK8B/An+aZD7J3lmvaY15F/AB4NIkD42vK2e9qDXmAuDuJA+z8EPXwar65ozXtGz+JrAkNbWunwFIks6cAZCkpgyAJDVlACSpKQMgSU0ZAElqygBIUlMGQJKa+n8y/EFnHMKhjAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "predict_validation_input_fn = lambda: my_input_fn(validation_examples, \n",
    "                                                  validation_targets[\"median_house_value_is_high\"], \n",
    "                                                  num_epochs=1, \n",
    "                                                  shuffle=False)\n",
    "\n",
    "validation_predictions = linear_regressor.predict(input_fn=predict_validation_input_fn)\n",
    "validation_predictions = np.array([item['predictions'][0] for item in validation_predictions])\n",
    "\n",
    "_ = plt.hist(validation_predictions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Assignment 2:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training model...\n",
      "LogLoss (on training data):\n",
      "  period 00 : 0.61\n",
      "  period 01 : 0.57\n",
      "  period 02 : 0.56\n",
      "  period 03 : 0.55\n",
      "  period 04 : 0.54\n",
      "  period 05 : 0.54\n",
      "  period 06 : 0.53\n",
      "  period 07 : 0.53\n",
      "  period 08 : 0.52\n",
      "  period 09 : 0.52\n",
      "Model training finished.\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def train_linear_classifier_model(\n",
    "    learning_rate,\n",
    "    steps,\n",
    "    batch_size,\n",
    "    training_examples,\n",
    "    training_targets,\n",
    "    validation_examples,\n",
    "    validation_targets):\n",
    "  \"\"\"Trains a linear regression model of one feature.\n",
    "  \n",
    "  In addition to training, this function also prints training progress information,\n",
    "  as well as a plot of the training and validation loss over time.\n",
    "  \n",
    "  Args:\n",
    "    learning_rate: A `float`, the learning rate.\n",
    "    steps: A non-zero `int`, the total number of training steps. A training step\n",
    "      consists of a forward and backward pass using a single batch.\n",
    "    batch_size: A non-zero `int`, the batch size.\n",
    "    training_examples: A `DataFrame` containing one or more columns from\n",
    "      `california_housing_dataframe` to use as input features for training.\n",
    "    training_targets: A `DataFrame` containing exactly one column from\n",
    "      `california_housing_dataframe` to use as target for training.\n",
    "    validation_examples: A `DataFrame` containing one or more columns from\n",
    "      `california_housing_dataframe` to use as input features for validation.\n",
    "    validation_targets: A `DataFrame` containing exactly one column from\n",
    "      `california_housing_dataframe` to use as target for validation.\n",
    "      \n",
    "  Returns:\n",
    "    A `LinearClassifier` object trained on the training data.\n",
    "  \"\"\"\n",
    "\n",
    "  periods = 10\n",
    "  steps_per_period = steps / periods\n",
    "  \n",
    "  # Create a linear classifier object.\n",
    "  my_optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)\n",
    "  my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)\n",
    "  linear_classifier = tf.estimator.LinearClassifier(\n",
    "      feature_columns=construct_feature_columns(training_examples),\n",
    "      optimizer=my_optimizer\n",
    "  )# YOUR CODE HERE: Construct the linear classifier.\n",
    "  \n",
    "  # Create input functions\n",
    "  training_input_fn = lambda: my_input_fn(training_examples, \n",
    "                                          training_targets[\"median_house_value_is_high\"], \n",
    "                                          batch_size=batch_size)\n",
    "  predict_training_input_fn = lambda: my_input_fn(training_examples, \n",
    "                                                  training_targets[\"median_house_value_is_high\"], \n",
    "                                                  num_epochs=1, \n",
    "                                                  shuffle=False)\n",
    "  predict_validation_input_fn = lambda: my_input_fn(validation_examples, \n",
    "                                                    validation_targets[\"median_house_value_is_high\"], \n",
    "                                                    num_epochs=1, \n",
    "                                                    shuffle=False)\n",
    "  \n",
    "  # Train the model, but do so inside a loop so that we can periodically assess\n",
    "  # loss metrics.\n",
    "  print(\"Training model...\")\n",
    "  print(\"LogLoss (on training data):\")\n",
    "  training_log_losses = []\n",
    "  validation_log_losses = []\n",
    "  for period in range (0, periods):\n",
    "    # Train the model, starting from the prior state.\n",
    "    linear_classifier.train(\n",
    "        input_fn=training_input_fn,\n",
    "        steps=steps_per_period\n",
    "    )\n",
    "    # Take a break and compute predictions.    \n",
    "    training_probabilities = linear_classifier.predict(input_fn=predict_training_input_fn)\n",
    "    training_probabilities = np.array([item['probabilities'] for item in training_probabilities])\n",
    "    \n",
    "    validation_probabilities = linear_classifier.predict(input_fn=predict_validation_input_fn)\n",
    "    validation_probabilities = np.array([item['probabilities'] for item in validation_probabilities])\n",
    "    \n",
    "    training_log_loss = metrics.log_loss(training_targets, training_probabilities)\n",
    "    validation_log_loss = metrics.log_loss(validation_targets, validation_probabilities)\n",
    "    # Occasionally print the current loss.\n",
    "    print(\"  period %02d : %0.2f\" % (period, training_log_loss))\n",
    "    # Add the loss metrics from this period to our list.\n",
    "    training_log_losses.append(training_log_loss)\n",
    "    validation_log_losses.append(validation_log_loss)\n",
    "  print(\"Model training finished.\")\n",
    "  \n",
    "  # Output a graph of loss metrics over periods.\n",
    "  plt.ylabel(\"LogLoss\")\n",
    "  plt.xlabel(\"Periods\")\n",
    "  plt.title(\"LogLoss vs. Periods\")\n",
    "  plt.tight_layout()\n",
    "  plt.plot(training_log_losses, label=\"training\")\n",
    "  plt.plot(validation_log_losses, label=\"validation\")\n",
    "  plt.legend()\n",
    "\n",
    "  return linear_classifier\n",
    "\n",
    "linear_classifier = train_linear_classifier_model(\n",
    "    learning_rate=0.000005,\n",
    "    steps=500,\n",
    "    batch_size=20,\n",
    "    training_examples=training_examples,\n",
    "    training_targets=training_targets,\n",
    "    validation_examples=validation_examples,\n",
    "    validation_targets=validation_targets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Assignment 3:\n",
    "**Note**: 一般情况下，只要不过拟合，就可以通过训练更长时间来提高AUC值，增加训练时间的方法有：1.增加步数 2.增加批量大小"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training model...\n",
      "LogLoss (on training data):\n",
      "  period 00 : 0.49\n",
      "  period 01 : 0.47\n",
      "  period 02 : 0.47\n",
      "  period 03 : 0.46\n",
      "  period 04 : 0.46\n",
      "  period 05 : 0.46\n",
      "  period 06 : 0.46\n",
      "  period 07 : 0.46\n",
      "  period 08 : 0.46\n",
      "  period 09 : 0.46\n",
      "Model training finished.\n",
      "AUC on the validation set: 0.81\n",
      "Accuracy on the validation set: 0.78\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# TUNE THE SETTINGS BELOW TO IMPROVE AUC\n",
    "linear_classifier = train_linear_classifier_model(\n",
    "    learning_rate=0.000003,\n",
    "    steps=20000,\n",
    "    batch_size=500,\n",
    "    training_examples=training_examples,\n",
    "    training_targets=training_targets,\n",
    "    validation_examples=validation_examples,\n",
    "    validation_targets=validation_targets)\n",
    "\n",
    "evaluation_metrics = linear_classifier.evaluate(input_fn=predict_validation_input_fn)\n",
    "\n",
    "print(\"AUC on the validation set: %0.2f\" % evaluation_metrics['auc'])\n",
    "print(\"Accuracy on the validation set: %0.2f\" % evaluation_metrics['accuracy'])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
